/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ldap_core.c                                        */
/*  NOTE      =                                                    */
/*  DATE      = 2015/07/27 by geyh                                 */
/*******************************************************************/
#include<stdio.h>
#include<sys/time.h>

#include "frct_comm.h"
#include "frdb_cursor.h"
#include "ldap_base_data.h"
#include "ldap_parse.h"
#include "ldap_core.h"
#include "frservice_comm.h"

extern void *g_p_apm_context;

/*******************************************************************************
*  FUNC     :  ldap私有信息创建
*  ARGS     :  void
*           :
*  RTN      :  NULL                     失败
*           :  p_st_private             成功
*  NOTE     :
*******************************************************************************/
FR_STATIC L7session_ldap_private* __ldap_private_create(void)
{
    L7session_ldap_private *p_st_private = NULL;

    p_st_private = (L7session_ldap_private*)frmalloc(sizeof(L7session_ldap_private));
    if(p_st_private == NULL)
        return NULL;

    memset(p_st_private, 0x00, sizeof(L7session_ldap_private));

    p_st_private->p_st_data = bytebuff_creat();
    if(p_st_private->p_st_data == NULL)
    {
        frfree(p_st_private);
        return NULL;
    }

    return p_st_private;

}


/*******************************************************************************
*  FUNC     :  ldap私有信息释放
*  ARGS     :  void *
*           :
*  RTN      :  FR_SUCC
*           :  FR_FAIL
*  NOTE     :
*******************************************************************************/
int ldap_session_destroy(void *p_private_session)
{
    L7session_ldap_private *p_st_private = (L7session_ldap_private*)p_private_session;
    if(p_st_private)
    {
        if(p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);
        if(p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if(p_st_private->p_lst_req_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

        if(p_st_private->p_lst_comm_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

        if(p_st_private->p_st_data)
            bytebuff_free(&p_st_private->p_st_data);

        if(p_st_private->p_title)
            frfree(p_st_private->p_title);

        if(p_st_private->p_user_name)
            frfree(p_st_private->p_user_name);

        frfree(p_st_private);
    }
    return FR_SUCC;

}

/*******************************************************************************
*  FUNC     :  ldap私有信息释放
*  ARGS     :  void *
*           :
*  RTN      :  FR_SUCC
*           :  FR_FAIL
*  NOTE     :
*******************************************************************************/
int __ldap_session_reset(void *p_private_session)
{
    L7session_ldap_private *p_st_private = (L7session_ldap_private*)p_private_session;

    if(p_st_private == NULL)
        return FR_FAIL;

    if(p_st_private->p_st_body_data_req)
        frreport_body_free(&p_st_private->p_st_body_data_req);
    if(p_st_private->p_st_body_data_resp)
        frreport_body_free(&p_st_private->p_st_body_data_resp);

    if(p_st_private->p_lst_req_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

    if(p_st_private->p_lst_comm_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

    if(p_st_private->p_st_data)
        bytebuff_free(&p_st_private->p_st_data);

    p_st_private->p_st_data = bytebuff_creat();
    if(p_st_private->p_st_data == NULL)
        return FR_FAIL;

    if(p_st_private->p_title)
    {
        frfree(p_st_private->p_title);
        p_st_private->p_title = NULL;
    }
    memset(&p_st_private->st_l4_trans, 0x00, sizeof(L4_transaction));
    p_st_private->i_mess_id = 0;
    p_st_private->ul_seq = 0;
    p_st_private->i_flag_data_type = 0;
    p_st_private->i_ret_rows = 0;

    return FR_SUCC;

}


/*******************************************************************************
*  FUNC     :  判断是否是ldap协议
*  ARGS     :  p_st_conn                    输入数据信息
*           :  p_st_packet                 输入数据
*  RTN      :  APM_L7_IS_NO                 不属于ldap协议
*           :  APM_L7_IS_YES                属于ldap协议
*  NOTE     :
*******************************************************************************/
int ldap_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    char *p_data = NULL;
    unsigned int ui_data_len = 0;
    int i_ret = 0;
    //unsigned int ui_skip_len = 0;
    if(p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len <= 2
       || p_st_conn==NULL)
        return APM_L7_IS_NO;

    p_data = p_st_packet->p_payload;

    //以 30开头
    if(*p_data != '\x30')
        return APM_L7_IS_NO;
    p_data++;

    //数据总长度 不包括长度位
    ui_data_len = (unsigned int)(*p_data);
    if(ui_data_len + 2 != p_st_packet->ui_payload_len)
        return APM_L7_IS_NO;

    //todo 设置方向
    i_ret = ldap_direction_detect(p_st_packet->p_payload, p_st_packet->ui_payload_len);
    if(i_ret == -1)
        return APM_L7_IS_NO;

    if(i_ret == 0)
        frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
    else
        frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);

    return APM_L7_IS_YES;

}

FR_STATIC int __ldap_session_report(Frreport_body_data *p_st_body_data, L7session_ldap_private *p_st_private)
{
    int i_tmp_len = 0;
    char arr_scope[64];
    char arr_option[32];
    char *p_title_tmp = NULL;

    if(p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(p_st_private->p_title)
    {
        switch(p_st_private->i_option)
        {
            case SEARCH_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "search ");
                break;

            case MOD_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "modify ");
                break;

            case ADD_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "add ");
                break;

            case DEL_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "del ");
                break;

            case MOD_DN_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "modDN ");
                break;

            case COM_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "compare ");
                break;

            case ABAND_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "abandon ");
                break;

            case EXT_REQ:
                snprintf(arr_option, sizeof(arr_option), "%s", "extended ");
                break;

            default:
                return FR_SUCC;
        }

        switch(p_st_private->i_scope)
        {
            case 0:
                snprintf(arr_scope, sizeof(arr_scope), "%s", "baseObject ");
                break;

            case 1:
                snprintf(arr_scope, sizeof(arr_scope), "%s", "singleLevel ");
                break;

            case 2:
                snprintf(arr_scope, sizeof(arr_scope), "%s", "wholeSubtree ");
                break;

            default:
                return FR_FAIL;
        }

        i_tmp_len = strlen(arr_scope) + strlen(arr_option) + strlen(p_st_private->p_title) + 2;
        p_title_tmp = (char *)frmalloc(i_tmp_len);
        if(p_title_tmp == NULL)
            return FR_FAIL;

        snprintf(p_title_tmp, i_tmp_len, "%s%s/%s", arr_option, p_st_private->p_title, arr_scope);
        frfree(p_st_private->p_title);
        p_st_private->p_title = p_title_tmp;

        if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, p_st_private->p_title) == FR_FAIL)
            return FR_FAIL;

    }

    if(p_st_private->st_login_timestamp.tv_sec)
    {
        if(p_st_private->p_user_name)
        {
            if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_USERNAME, p_st_private->p_user_name) == FR_FAIL)
                return FR_FAIL;
        }

        if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_ID, p_st_private->arr_session_id) == FR_FAIL)
            return FR_FAIL;

        if(frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP, &p_st_private->st_login_timestamp) == FR_FAIL)
            return FR_FAIL;
    }

    return FR_SUCC;
}


/*******************************************************************************
*  FUNC     :  ldap的packet解析
*  ARGS     :  p_st_conn                (入力链接信息)
            :  p_st_packet             (入力packet信息)
            :  p_st_hash_report         (保存Frreport_data)
*  RTN      :  APM_L7_ANALYZE_SUCC         成功
*           :  APM_L7_ANALYZE_TODO         数据未结束
*           :  APM_L7_ANALYZE_FAIL         失败
*  NOTE     :
*******************************************************************************/
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_ldap_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    unsigned long ul_tmp = 0;
    char arr_info[1024];

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_ldap_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if(p_st_private->p_st_body_data_req)
    {
        i_ret = __ldap_session_reset((void *)(p_st_private));
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    //st_request_time_first_byte
    if(p_st_l4_trans->st_request_time_first_byte.tv_sec == 0)
    {
        p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        if(p_st_private->p_st_body_data_req == NULL)
        {
            p_st_private->p_st_body_data_req =frreport_body_new_l7(p_st_conn);
            if(p_st_private->p_st_body_data_req == NULL)
                return APM_L7_ANALYZE_FAIL;
        }

        if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        if(frreport_body_l7_add_int(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, FR_YES) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_packet->st_timestamp) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

    }


    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    /* 请求的字节数 */
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    i_ret = bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    //req解析
    i_ret = ldap_parse_req(p_st_private->p_st_data, p_st_private->p_st_body_data_req, p_st_private);
    if(p_st_private->i_flag_data_type == FRLOGOUT_END)
    {

        if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
            snprintf(arr_info, sizeof(arr_info), "%s logout", p_st_private->p_user_name);
        else
            snprintf(arr_info, sizeof(arr_info), "logout");

        p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGOUT, arr_info, &p_st_packet->st_timestamp);

        p_st_private->i_flag_data_type = 0;
        if (p_st_report_data)
        {
            if(frreport_send(g_p_apm_context, &p_st_report_data) == FR_FAIL)
            {
                frreport_data_free(&p_st_report_data);
                return APM_L7_ANALYZE_FAIL;
            }
        }
        frreport_body_free (&p_st_private->p_st_body_data_req);
        return APM_L7_ANALYZE_SET_REQ (APM_L7_ANALYZE_SUCC);
    }

    if(i_ret == APM_L7_ANALYZE_SUCC && p_st_private->i_flag_report)
    {
        if(p_st_private->i_flag_data_type == FRLOGIN_START)
        {
            p_st_private->st_login_timestamp.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_private->st_login_timestamp.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        if(p_st_private->p_user_name || p_st_private->p_title)
        {
            i_ret = __ldap_session_report(p_st_private->p_st_body_data_req, p_st_private);
            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;
        }

        if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        ul_tmp = frtime_diff(&p_st_l4_trans->st_request_time_first_byte, &p_st_l4_trans->st_request_time);
        if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        if(frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        p_st_private->p_lst_comm_tmp = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
        if(p_st_private->p_lst_comm_tmp == NULL)
            return APM_L7_ANALYZE_FAIL;

        p_st_private->p_lst_req_tmp = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
        if(p_st_private->p_lst_req_tmp == NULL)
            return APM_L7_ANALYZE_FAIL;

        p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
        if(p_st_report_data == NULL)
            return APM_L7_ANALYZE_FAIL;

        if(frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
        {
            frreport_data_free(&p_st_report_data);
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_private->p_st_body_data_req = NULL;

        if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        {
            frreport_data_free(&p_st_report_data);
            return APM_L7_ANALYZE_FAIL;
        }

        return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
    }
    else
    {
        //不需要上报数据 数据清除
        bytebuff_free(&p_st_private->p_st_data);
        p_st_private->p_st_data = bytebuff_creat();
        if(p_st_private->p_st_data == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    return i_ret;

}


/*******************************************************************************
*  FUNC     :  ldap的packet解析
*  ARGS     :  p_st_conn                (入力链接信息)
            :  p_st_packet             (入力packet信息)
            :  p_st_hash_report         (保存Frreport_data)
*  RTN      :  APM_L7_ANALYZE_SUCC         成功
*           :  APM_L7_ANALYZE_TODO         数据未结束
*           :  APM_L7_ANALYZE_FAIL         失败
*  NOTE     :
*******************************************************************************/
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_ldap_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    unsigned long ul_tmp = 0 ;
    Frreport_data *p_st_report_data = NULL;
    char arr_info[1024];

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_ldap_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 &&
        p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
    {
        if(p_st_private->p_st_body_data_resp == NULL)
        {
            p_st_private->p_st_body_data_resp =frreport_body_new_l7(p_st_conn);
            if(p_st_private->p_st_body_data_resp == NULL)
                return APM_L7_ANALYZE_FAIL;
        }

        //comm 信息
        if(p_st_private->p_lst_comm_tmp)
        {
            //comm
            if(FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_comm_tmp) == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            //把req数据链表添加到resp中
            if(FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_req_tmp) == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            i_ret = frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_resp, p_st_conn);
            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;
        }

        //应答发起时间戳
        p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        //首包时间
        ul_tmp = frtime_diff(&p_st_l4_trans->st_request_time, &p_st_l4_trans->st_response_time_first_byte);
        if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;
    /* 请求的字节数 */
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    //resp解析
    i_ret = bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    //req解析
    i_ret = ldap_parse_resp(p_st_private->p_st_data, p_st_private->p_st_body_data_resp, p_st_private);
    if(p_st_private->i_flag_data_type && i_ret == APM_L7_ANALYZE_SUCC)
    {
        if (p_st_private->i_flag_data_type == FRLOGIN_SUCC)
        {
            if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                snprintf(arr_info, sizeof(arr_info), "%s login", p_st_private->p_user_name);
            else
                snprintf(arr_info, sizeof(arr_info), "login");

            p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON, arr_info, &p_st_packet->st_timestamp);

        }
        else if (p_st_private->i_flag_data_type == FRLOGIN_FAIL)
        {
            if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                snprintf(arr_info, sizeof(arr_info), "%s login reject", p_st_private->p_user_name);
            else
                snprintf(arr_info, sizeof(arr_info), "login reject");

            p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON_REJECT, arr_info, &p_st_packet->st_timestamp);

        }

        p_st_private->i_flag_data_type = 0;
        if (p_st_report_data)
        {
            if(frreport_send(g_p_apm_context, &p_st_report_data) == FR_FAIL)
            {
                frreport_data_free(&p_st_report_data);
                return APM_L7_ANALYZE_FAIL;
            }
        }
    }

    if(i_ret == APM_L7_ANALYZE_SUCC && p_st_private->i_flag_report)
    {
        if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        ul_tmp = frtime_diff(&p_st_l4_trans->st_response_time_first_byte, &p_st_l4_trans->st_response_time);
        if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        if(frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
        if(p_st_report_data == NULL)
            return APM_L7_ANALYZE_FAIL;

        if(frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
        {
            frreport_data_free(&p_st_report_data);
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_private->p_st_body_data_resp = NULL;

        if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        {
            frreport_data_free(&p_st_report_data);
            return APM_L7_ANALYZE_FAIL;
        }

        if(__ldap_session_reset(p_st_private) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
    }

    if(i_ret == APM_L7_ANALYZE_SUCC && p_st_private->i_flag_report == 0)
    {
        bytebuff_free(&p_st_private->p_st_data);
        p_st_private->p_st_data = bytebuff_creat();
        if(p_st_private->p_st_data == NULL)
            return APM_L7_ANALYZE_FAIL;

        return APM_L7_ANALYZE_TODO;
    }

//    if(i_ret == APM_L7_ANALYZE_FAIL)
//    {
//        printf("p_st_packet->st_timestamp.tv_usec = %d\n", p_st_packet->st_timestamp.tv_usec);
//    }

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  ldap协议解析
*  ARGS     :  p_st_conn                    输入数据信息
*           :  p_st_packet                 输入数据
*           :  p_st_hash_report
*  RTN      :
*           :
*  NOTE     :
*******************************************************************************/
int ldap_analysis(Conntrack *p_st_conn
                  , Apm_packet *p_st_packet
                  , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_ldap_private *p_st_private = NULL;
    L7_session *p_st_session = NULL;

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin syn 包  销毁私有数据
    if(p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        ldap_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    p_st_private = (L7session_ldap_private*)p_st_session->p_session_private;

    if(p_st_private == NULL)
    {
        p_st_private = __ldap_private_create();
        if(p_st_private == NULL)
            return APM_L7_ANALYZE_FAIL;

        p_st_session->p_session_private = p_st_private;
        fruuid(p_st_session->arr_session_id);

    }

    //request
    if(p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn,p_st_packet,p_st_hash_report,p_st_session);
        if(i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }
    else//response
    {
        i_ret = __resp_data_analysis(p_st_conn,p_st_packet,p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }

ERROR:
    if(p_st_session->p_session_private)
        __ldap_session_reset(p_st_session->p_session_private);

    return APM_L7_ANALYZE_FAIL;

}

